<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>ObjectTemplates</title>
<style type="text/css">

/*
Author: Peter Parente
Date: 2008/01/22
Version: 1.0
Copyright: This stylesheet has been placed in the public domain - free to edit and use for all uses.
*/

body {
  font: 100% serif;
  background: #ffffff;
  color: black;
  margin: 2em;
  padding: 0em 2em;
  background-color: honeydew;
}

p.topic-title {
  font-weight: bold;
}

table.docinfo {
  text-align: left;
  margin: 2em 0em;
}

a[href] {
  color: #436976;
  background-color: transparent;
}

a.toc-backref {
  text-decoration: none;
}

h1 a[href] {
  color: #003a6b;
  text-decoration: none;
  background-color: transparent;
}

a.strong {
  font-weight: bold;
}

img {
  margin: 0;
  border: 0;
}

p {
  margin: 0.5em 0 1em 0;
  line-height: 1.5em;
}

p a:visited {
  color: purple;
  background-color: transparent;
}

p a:active {
  color: red;
  background-color: transparent;
}

a:hover {
  text-decoration: none;
}

p img {
  border: 0;
  margin: 0;
}

p.rubric {
  font-weight: bold;
  font-style: italic;
}

h1.title {
  color: #003a6b;
  font-size: 250%;
  margin-bottom: 0em;
}

h2.subtitle {
  color: #003a6b;
  border-bottom: 0px;
}

h1, h2, h3, h4, h5, h6 {
  color: #555;
  background-color: transparent;
  margin: 0em;
  padding-top: 0.5em;
}

h1 {
  font-size: 160%;
  margin-bottom: 0.5em;
  border-bottom: 2px solid #aaa;
}

h2 {
  font-size: 140%;
  margin-bottom: 0.5em;
  border-bottom: 1px solid #aaa;
}

h3 {
  font-size: 130%;
  margin-bottom: 0.5em;
}

h4 {
  font-size: 110%;
  font-weight: bold;
  margin-bottom: 0.5em;
}

h5 {
  font-size: 105%;
  font-weight: bold;
  margin-bottom: 0.5em;
}

h6 {
  font-size: 100%;
  font-weight: bold;
  margin-bottom: 0.5em;
}

dt {
  font-style: italic;
}

dd {
  margin-bottom: 1.5em;
}

div.admonition, div.note, div.tip, div.caution, div.important {
  margin: 2em 2em;
  padding: 0em 1em;
  border-top: 1px solid #aaa;
  border-left: 1px solid #aaa;
  border-bottom: 2px solid #555;
  border-right: 2px solid #555;
}

div.important {
  background: transparent url('../images/important.png') 10px 2px no-repeat;
}

div.caution {
  background: transparent url('../images/caution.png') 10px 2px no-repeat;
}

div.note {
  background: transparent url('../images/note.png') 10px 2px no-repeat;
}

div.tip {
  background: transparent url('../images/tip.png') 10px 2px no-repeat;
}

div.admonition-example {
  background: transparent url('../images/tip.png') 10px 2px no-repeat;
}

div.admonition-critical-example {
  background: transparent url('../images/important.png') 10px 2px no-repeat;
}

p.admonition-title {
  font-weight: bold;
  border-bottom: 1px solid #aaa;
  padding-left: 30px;
}

table.docutils {
  text-align: left;
  border: 1px solid gray;
  border-collapse: collapse;
  width: 100%;
  margin: 1.5em 0em;
}

table.docutils caption {
  font-style: italic;
}

table.docutils td, table.docutils th {
  padding: 0.25em 0.5em;
}

table.docutils th {
  background-color: #dddddd;
}

div.sidebar {
  width: 33%;
  float: right;
  margin: 0em 2em;
  padding: 0em 1em;
  border-top: 1px solid #aaa;
  border-left: 1px solid #aaa;
  border-bottom: 2px solid #555;
  border-right: 2px solid #555;
}

p.sidebar-title {
  margin-bottom: 0em;
  color: #003a6b;
  border-bottom: 1px solid #aaa;
  font-weight: bold;
}

p.sidebar-subtitle {
  margin-top: 0em;
  font-style: italic;
  color: #003a6b;
}

pre.literal-block, pre.doctest-block {
  border: thin black solid;
  padding: 5px;
  background-color: lightsteelblue;
}

code, tt {
  color: #000066;
}
</style>
</head>
<body>
<div class="document" id="objecttemplates">
<h1 class="title">ObjectTemplates</h1>

<p>ObjectTemplates are a template for creating objects. They work well with Factories.</p>
<p>A <strong>Bunch</strong> is simply a bunch of attributes. Keyword arguments to a Bunch are turned into attributes:</p>
<pre class="doctest-block">
&gt;&gt;&gt; b = Bunch(pants=42, shirt=15)
&gt;&gt;&gt; b.pants
42
&gt;&gt;&gt; b.shirt
15
</pre>
<p>Calling a bunch returns a new copy:</p>
<pre class="doctest-block">
&gt;&gt;&gt; c = b()
&gt;&gt;&gt; c.__dict__ == b.__dict__
True
&gt;&gt;&gt; c is b
False
</pre>
<p>When called, an <strong>ObjectTemplate</strong> instance produces a new instance
of <tt class="docutils literal"><span class="pre">bunchClass</span></tt>. Attributes on the template are passed as kwargs
to the bunch.  However, if an attribute is callable, it is called
and the return value is used instead:</p>
<pre class="doctest-block">
&gt;&gt;&gt; counter = itertools.count(1).next # an incrementing counter
&gt;&gt;&gt; def color():
...     return &quot;blue&quot;
&gt;&gt;&gt; template = ObjectTemplate(size=42,
...                           color=color,
...                           count=counter,
...                           bunchClass=Bunch)
&gt;&gt;&gt; bunch = template()
&gt;&gt;&gt; isinstance(bunch, Bunch)
True
&gt;&gt;&gt; bunch.size
42
&gt;&gt;&gt; bunch.color
'blue'
&gt;&gt;&gt; bunch.count
1
</pre>
<p>Each call to the template produces a new bunch.  Any functions will
be called again:</p>
<pre class="doctest-block">
&gt;&gt;&gt; bunch2 = template()
&gt;&gt;&gt; bunch2.count
2
</pre>
<p>If you want to pass a callable object to the bunch, wrap it in a lambda:</p>
<pre class="doctest-block">
&gt;&gt;&gt; template = ObjectTemplate()
&gt;&gt;&gt; template.return_val = color
&gt;&gt;&gt; template.a_function = lambda: color
&gt;&gt;&gt; bunch = template()
&gt;&gt;&gt; bunch.return_val
'blue'
&gt;&gt;&gt; bunch.a_function #doctest:+ELLIPSIS
&lt;function color at ...&gt;
</pre>
<p>ObjectTemplate can be used for configuration:</p>
<pre class="literal-block">
config = ObjectTemplate()

# in production
config.path = &quot;/var/myapp/&quot;
config.debug_level = logging.WARN

# in tests
config.path = Factory(tempfile.mktemp)
config.debug_level = logging.DEBUG

# app code
def do_stuff_with_config(config):
     config = config.harden() # call any factories

     output = file(config.path)
     logging.setLevel(config.debug_level)
</pre>
</div>
</body>
</html>
